package top.atcra.rpc.transport.common;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import top.atcra.rpc.RPCBootstrap;
import top.atcra.rpc.exception.RemoteCallException;
import top.atcra.rpc.transport.message.RPCResponse;
import top.atcra.rpc.transport.message.RPCResponseCode;

import java.util.concurrent.CompletableFuture;


/**
 * 处理服务端响应的handler。该类的功能在于：
 * 在发出请求时，会将一个completableFuture放入全局的挂起的请求中。
 * 当收到响应时，会从全局的挂起的请求中寻找与之匹配的待处理的completableFuture，并将响应结果放入其中。
 *
 * @author atcra
 * @date 2025-3-25
 */
@Slf4j
public class PendingRequestHandler extends SimpleChannelInboundHandler<RPCResponse> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, RPCResponse response){
        // 从全局的挂起的请求中寻找与之匹配的待处理的completableFuture
        var pair = ctx.channel().attr(RPCBootstrap.PENDING_CALLS_KEY).get().get(response.getRequestId());
        CompletableFuture<Object> completableFuture = pair.getKey();
        // 刷新响应时间
//        ServiceHealthDetector.updateServiceTTL(ctx.channel(), System.currentTimeMillis() - pair.getValue());
        if (completableFuture == null) {
            throw new RuntimeException(String.format("未找到编号为【%dl】的completableFuture，无法处理响应结果。", response.getRequestId()));
        }
        switch (RPCResponseCode.valueOf(response.getCode())) {
            case SUCCESS -> {
                Object returnValue = response.getBody();
                completableFuture.complete(returnValue);
                if (log.isDebugEnabled()) {
                    log.debug("找到编号为【{}】的completableFuture，处理响应结果。", response.getRequestId());
                }
            }
            case HEARTBEAT_SUCCESS -> {
                // TODO: 心跳响应，后续可以承载更多信息，如服务端负载等
                completableFuture.complete(null);
                if (log.isDebugEnabled()) {
                    log.debug("收到心跳响应，地址为【{}】的服务仍然存活。", ctx.channel().remoteAddress());
                }
            }
            case METHOD_NOT_FOUND -> {
                // 处理方法未找到的响应
                completableFuture.completeExceptionally(new NoSuchMethodException("方法未找到"));
                if (log.isDebugEnabled()) {
                    log.debug("请求【{}】所请求的方法{}不存在", response.getRequestId(),response.getBody());
                }
            }
            case FAIL -> {
                // 处理失败的响应
                completableFuture.completeExceptionally(new RemoteCallException("服务调用失败"));
                if (log.isDebugEnabled()) {
                    log.debug("请求【{}】调用失败,原因为：{}",response.getRequestId(), response.getBody());
                }
            }
            case CLOSING -> {
                // 处理服务关闭的响应
                completableFuture.completeExceptionally(new RemoteCallException("服务正在关闭中"));
                if (log.isDebugEnabled()) {
                    log.debug("请求【{}】的目标服务器正在关闭中，拒绝新请求。", response.getRequestId());
                }
            }
            case null, default -> throw new RuntimeException(response.getRequestId()+"未知的响应码:" + response.getCode());
        }
        // 从全局的挂起的请求中删除该请求
//        RPCBootstrap.PENDING_CALLS.remove(response.getRequestId());
    }
}
